﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using Boardgame;

namespace WinGameControls
{
    public partial class WinCheckerboard : UserControl
    {
        private Icon[,] boardIcons;
        private bool[,] isHilited;

        public event EventHandler LeftClick;
        public event EventHandler RightDown;
        public event EventHandler RightUp;

        public WinCheckerboard ()
        {
            InitializeComponent();

            // Designer defaults:
            Dimensions = new Point (8, 8);
            LightCells = Color.SandyBrown;
            DarkCells = Color.Chocolate;
        }

        [Category ("Layout"), Description ("Number of cells in file and rank")]
        public Point Dimensions { get; set; }

        [Category ("Appearance"), Description ("Color of lower right cell")]
        public Color LightCells { get; set; }

        [Category ("Appearance"), Description ("Color of lower left cell")]
        public Color DarkCells { get; set; }

        [Browsable (false)]
        public Cell? Selection { get; private set; }


        private Cell CellFromPixel (int x, int y)
        {
            var cell = new Cell
            (
                x * Dimensions.X / Size.Width,
                (Size.Height - y - 1) * Dimensions.Y / Size.Height
            );
            return cell;
        }


        private Point PixelFromCell (int cellX, int cellY)
        {
            // This math ensures that for the origin (lower left) of a cell of (x, y),
            // PixelFromCell (CellFromPixel (x, y)) == x, y
            var pixel = new Point
            (
                Size.Width - (Dimensions.X - cellX) * Size.Width / Dimensions.X,
                (Dimensions.Y - cellY) * Size.Height / Dimensions.Y - 1
            );
            return pixel;
        }

        #region Model events handlers

        public void ClearSelection ()
        {
            if (Selection.HasValue)
            {
                SetHilite (Selection.Value.X, Selection.Value.Y, false);
                Selection = null;
            }
        }

        public void SetSelection (int cellX, int cellY)
        {
            if (Selection.HasValue && Selection.Value.X != cellX && Selection.Value.Y != cellY)
                ClearSelection();
            Selection = new Cell (cellX, cellY);
            SetHilite (cellX, cellY, true);
        }


        public void SetHilite (int cellX, int cellY, bool isHilite)
        {
            this.isHilited[cellX,cellY] = isHilite;
            InvalidateCell (cellX, cellY);
        }

        public void ClearHilites ()
        {
            ClearSelection();

            for (var cellY = 0; cellY < Dimensions.Y; ++cellY)
                for (var cellX = 0; cellX < Dimensions.X; ++cellX)
                    if (isHilited[cellX,cellY])
                    {
                        this.isHilited[cellX,cellY] = false;
                        InvalidateCell (cellX, cellY);
                    }
        }


        public void SetIcon (int cellX, int cellY, Icon icon)
        {
            boardIcons[cellX,cellY] = icon;
            InvalidateCell (cellX, cellY);
        }


        private void InvalidateCell (int cellX, int cellY)
        {
            Point p0 = PixelFromCell (cellX, cellY),
                  p1 = PixelFromCell (cellX+1, cellY+1);

            Invalidate (new Rectangle (p0.X, p1.Y+1, p1.X-p0.X, p0.Y-p1.Y));
            Update();

            Debug.WriteLine (String.Format ("Invalidated {0},{1} size={2},{3}", p0.X, p0.Y, p1.X-p0.X, p0.Y-p1.Y));
        }

        #endregion

        #region Widget events handlers

        private void WinCheckerboard_Load (object sender, EventArgs args)
        {
            boardIcons = new Icon[Dimensions.X, Dimensions.Y];
            isHilited = new bool[Dimensions.X, Dimensions.Y];
        }


        private void WinCheckerboard_EnabledChanged (object sender, EventArgs args)
        {
            if (! Enabled)
                ClearSelection();
        }


        private void WinCheckerboard_MouseClick (object sender, MouseEventArgs mArgs)
        {
            if (mArgs.Button == MouseButtons.Left)
            {
                var cell = CellFromPixel (mArgs.X, mArgs.Y);
                var evArg = new WinCheckerboardClickArgs (cell.X, cell.Y);
                if (LeftClick != null)
                    LeftClick (this, evArg);
            }
        }


        private void WinCheckerboard_MouseDown (object sender, MouseEventArgs mArgs)
        {
            if (mArgs.Button == MouseButtons.Right)
            {
                var cell = CellFromPixel (mArgs.X, mArgs.Y);
                if (RightDown != null)
                    RightDown (this, new WinCheckerboardClickArgs (cell.X, cell.Y));
            }
        }


        private void WinCheckerboard_MouseUp (object sender, MouseEventArgs mArgs)
        {
            if (mArgs.Button == MouseButtons.Right)
                if (RightUp != null)
                    RightUp (this, null);
        }


        private void WinCheckerboard_Paint (object sender, PaintEventArgs pArgs)
        {
            SolidBrush hiliteBrush = new SolidBrush (Color.Purple);
            SolidBrush darkBrush = new SolidBrush (DarkCells);
            SolidBrush lightBrush = new SolidBrush (LightCells);

            var cell0 = CellFromPixel (pArgs.ClipRectangle.X, pArgs.ClipRectangle.Y);
            var cell1 = CellFromPixel (pArgs.ClipRectangle.Right-1, pArgs.ClipRectangle.Bottom-1);

            for (int cellY = cell1.Y; cellY <= cell0.Y; ++cellY)
                for (int cellX = cell0.X; cellX <= cell1.X; ++cellX)
                {
                    Debug.WriteLine ("Drawing cell (" + cellX + "," + cellY + ")");

                    var p0 = PixelFromCell (cellX, cellY);
                    var p1 = PixelFromCell (cellX+1, cellY+1);

                    SolidBrush plain = (cellX + cellY) % 2 == 0 ? darkBrush : lightBrush;
                    SolidBrush brush = isHilited[cellX,cellY] ? hiliteBrush : plain;

                    var cellBox = new Rectangle (p0.X, p1.Y+1, p1.X-p0.X, p0.Y-p1.Y);
                    pArgs.Graphics.FillRectangle (brush, cellBox);

                    if (isHilited[cellX,cellY])
                    {
                        Pen borderPen = new Pen (lightBrush);
                        var cellBorder = new Point[]
                        {
                          new Point (p0.X, p0.Y),
                          new Point (p1.X-1, p0.Y),
                          new Point (p1.X-1, p1.Y+1),
                          new Point (p0.X, p1.Y+1)
                        };
                        pArgs.Graphics.DrawPolygon (borderPen, cellBorder);
                    }

                    Icon icon = boardIcons[cellX,cellY];
                    if (icon != null)
                        pArgs.Graphics.DrawIcon (icon, cellBox);
                }

            hiliteBrush.Dispose();
            darkBrush.Dispose();
            lightBrush.Dispose();
        }


        private void WinCheckerboard_Resize (object sender, EventArgs args)
        {
            Invalidate();
        }

        #endregion
    }
}
